package com.xwb.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.slf4j.Logger;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

//方式三：注解实现
@Aspect
@Component
public class ContrllerAspect {
//    @Before("execution(* com.xwb.controller.UserController.*(..))")//（。。）是不管有多少个参数的意思
//    public void before(){
//        System.out.println("======方法执行前=====");
//    }
//
    private Logger logger = LoggerFactory.getLogger(ContrllerAspect.class);

    @After("execution(* com.xwb.controller.UserController.*(..))")
    public void after(JoinPoint jp) throws Throwable{
        System.out.println("======方法执行后====");
        System.out.println(jp.getSignature().getClass());
        System.out.println("方法名："+jp.getSignature().getName());
        Object[] args = jp.getArgs();
        for(Object o :args){
            System.out.println("切入方法的参数值："+o);
        }
//       // 静态方法获取参数名和参数值
//        Map fieldsName = ContrllerAspect.getFieldsName(jp);
//        for(Object o :fieldsName.keySet()) {
//            System.out.println("切入方法的参数名：" +o);
//        }
//        for(Object o :args){
//            System.out.println("切入方法的参数类型："+o.getClass().getName());
//        }

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 记录下请求内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        logger.info("CLASS_METHOD : " + jp.getSignature().getDeclaringTypeName() + "." + jp.getSignature().getName());
        logger.info("TIME:"+new Date());
        logger.info("ARGS : " + Arrays.toString(jp.getArgs()));

    }

    //在环绕增强中，我们可以给定一个参数，代表我们要获取处理切入的点：
//    @Around("execution(* com.xwb.controller.UserController.*(..))")
//    public void around(ProceedingJoinPoint jp) throws Throwable {
//        System.out.println("环绕前");
//        //执行方法
//        Object proceed = jp.proceed();
//        //Object[] args= jp.getArgs();
//        //System.out.println(args.toString());
//        System.out.println(jp.getSignature().getClass());
//        System.out.println("方法名："+jp.getSignature().getName());
//        Object[] args = jp.getArgs();
//        for(Object o :args){
//            System.out.println("切入方法的参数值："+o);
//        }
        //静态方法获取参数名和参数值
//        Map fieldsName = ContrllerAspect.getFieldsName(jp);
//        for(Object o :fieldsName.keySet()) {
//            System.out.println("切入方法的参数名：" +o);
//        }
//        for(Object o :args){
//            System.out.println("切入方法的参数类型："+o.getClass().getName());
//        }

   // }


    //输出一个map包含JP的参数名和参数值
//    private static HashMap<String, Class> map = new HashMap<String, Class>() {
//        {
//            put("java.lang.Integer", int.class);
//            put("java.lang.Double", double.class);
//            put("java.lang.Float", float.class);
//            put("java.lang.Long", long.class);
//            put("java.lang.Short", short.class);
//            put("java.lang.Boolean", boolean.class);
//            put("java.lang.Char", char.class);
//        }
//    };
//
//    private static Map getFieldsName(JoinPoint jp) throws ClassNotFoundException, NoSuchMethodException {
//        String classType = jp.getTarget().getClass().getName();
//        String methodName = jp.getSignature().getName();
//        // 参数值
//        Object[] args = jp.getArgs();
//        Class<?>[] classes = new Class[args.length];
//        for (int k = 0; k < args.length; k++) {
//            if (!args[k].getClass().isPrimitive()) {
//                // 获取的是封装类型而不是基础类型
//                String result = args[k].getClass().getName();
//                Class s = map.get(result);
//                classes[k] = s == null ? args[k].getClass() : s;
//            }
//        }
//        ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
//        // 获取指定的方法，第二个参数可以不传，但是为了防止有重载的现象，还是需要传入参数的类型
//        Method method = Class.forName(classType).getMethod(methodName, classes);
//        // 参数名
//        String[] parameterNames = pnd.getParameterNames(method);
//        // 通过map封装参数和参数值
//        HashMap<String, Object> paramMap = new HashMap();
//        for (int i = 0; i < parameterNames.length; i++) {
//            paramMap.put(parameterNames[i], args[i]);
//        }
//        return paramMap;
//    }
}
